/*
 * Copyright (c) 2018-2023 北京华恒盛世科技有限公司
 * QUICKPOOL is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *     http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
*/

#include "xdrbase.h"
#include "channel.h"
#include "api.h"

static int signal_map[] = {
    QUICKPOOL_SIGNAL_NULL,
    QUICKPOOL_SIGCHKPNT,

    QUICKPOOL_SIGSTOP_USER,
    QUICKPOOL_SIGSTOP_LOAD,
    QUICKPOOL_SIGSTOP_PREEMPT,
    QUICKPOOL_SIGSTOP_WINDOW,
    QUICKPOOL_SIGSTOP_OTHER,

    QUICKPOOL_SIGCONT_USER,
    QUICKPOOL_SIGCONT_LOAD,
    QUICKPOOL_SIGCONT_WINDOW,
    QUICKPOOL_SIGCONT_OTHER,

    QUICKPOOL_SIGKILL_USER,
    QUICKPOOL_SIGKILL_OTHER,
    QUICKPOOL_SIGKILL_RUNLIMIT,
    QUICKPOOL_SIGKILL_DEADLINE,
    QUICKPOOL_SIGKILL_PROCESSLIMIT,
    QUICKPOOL_SIGKILL_FORCE,
    QUICKPOOL_SIGKILL_REQUEUE,
    QUICKPOOL_SIGKILL_CPULIMIT,
    QUICKPOOL_SIGKILL_MEMLIMIT,
    QUICKPOOL_SIGKILL_SWAPLIMIT,
};

static const char *signal_symbol[] = {
    "NO_SIGNAL",
    "CHKPNT",

    "SUSPEND_USER",
    "SUSPEND_LOAD",
    "SUSPEND_PREEMPT",
    "SUSPEND_WINDOW",
    "SUSPEND_OTHER",

    "RESUME_USER",
    "RESUME_LOAD",
    "RESUME_WINDOW",
    "RESUME_OTHER",

    "KILL_USER",
    "KILL_OTHER",
    "KILL_RUNLIMIT",
    "KILL_DEADLINE",
    "KILL_PROCESSLIMIT",
    "FORCE_KILL",
    "KILL_REQUEUE",
    "KILL_CPULIMIT",
    "KILL_MEMLIMIT",
    "KILL_SWAPLIMIT",
};


static int defaultSigValue[] = {
    QUICKPOOL_SIGNAL_NULL,
    QUICKPOOL_SIGCHKPNT,

    SIGSTOP,
    SIGSTOP,
    SIGSTOP,
    SIGSTOP,
    SIGSTOP,

    SIGCONT,
    SIGCONT,
    SIGCONT,
    SIGCONT,

    SIGKILL,
    SIGKILL,
    SIGKILL,
    SIGKILL,
    SIGKILL,
    SIGKILL,
    SIGKILL,
    SIGKILL,
    SIGKILL,
    SIGKILL,
};

/**
 * @brief       API: transfer signal string to quickpool signal value.
 *
 * @param[in]   sigstring    #1: input signal string
 *
 * @retval      <INFINIT_INT #1: succeed
 * @retval      INFINIT_INT  #2: failed, something wrong with the string
 *
 * @note        singnal string could be system signal, or quickpool singal.
 */
int
string_2qpsignal(const char *sigstring)
{
    if ((NULL == sigstring) || ('\0' == sigstring[0])) {
        return (INFINIT_INT);
    }

    int i;
    for (i=0; i<QUICKPOOL_SIGNAL_NUMBER; i++) {
        if (0 == strcmp(signal_symbol[i], sigstring)) {
            return (signal_map[i]);
        }
    }

    int sigValue;
    sigValue = gf_string_2signal(sigstring);
    if (0 < sigValue) {
        return (sigValue);
    }

    return (INFINIT_INT);
} // end function string_2qpsignal

/**
 * @brief       API: transfer quickpool signal value to string.
 *
 * @param[in]   signal       #1: input signal value
 * @param[out]  sigstring    #1: signal string
 *
 * @note        singnal value could be system signal, or quickpool singal.
 */
void
qpsignal_2string(int signal, char *sigstring)
{
    if (0 <= signal) {
        sigstring = gf_signal_2string(signal);
        return;
    }

    if (-signal < QUICKPOOL_SIGNAL_NUMBER) {
        strcpy(sigstring, signal_symbol[-signal]);
    } else {
        strcpy(sigstring, "UNKNOWN");
    }

    return;
} // end function qpsignal_2string

/**
 * @brief       Get default signal value.
 *
 * @param[in]   signal       #1: signal value
 * @param[in]   actcmd       #2: job control command
 *
 * @retval      signal       #1: succeed, default signal value
 */
int
get_signal_value(int signal, char *actcmd)
{
    if (0 <= signal) {
        return (signal);
    }

    switch (signal) {
    case QUICKPOOL_SIGSTOP_USER:
    case QUICKPOOL_SIGSTOP_LOAD:
    case QUICKPOOL_SIGSTOP_PREEMPT:
    case QUICKPOOL_SIGSTOP_WINDOW:
    case QUICKPOOL_SIGSTOP_OTHER:

    case QUICKPOOL_SIGCONT_USER:
    case QUICKPOOL_SIGCONT_LOAD:
    case QUICKPOOL_SIGCONT_WINDOW:
    case QUICKPOOL_SIGCONT_OTHER:

    case QUICKPOOL_SIGKILL_USER:
    case QUICKPOOL_SIGKILL_OTHER:
    case QUICKPOOL_SIGKILL_RUNLIMIT:
    case QUICKPOOL_SIGKILL_DEADLINE:
    case QUICKPOOL_SIGKILL_PROCESSLIMIT:
    case QUICKPOOL_SIGKILL_FORCE:
    case QUICKPOOL_SIGKILL_REQUEUE:
    case QUICKPOOL_SIGKILL_CPULIMIT:
    case QUICKPOOL_SIGKILL_MEMLIMIT:
    case QUICKPOOL_SIGKILL_SWAPLIMIT:
        if ((NULL == actcmd) || ('\0' == actcmd[0])) {

            return (defaultSigValue[-signal]);
        } else {

            int defSigValue;
            defSigValue = string_2qpsignal(actcmd);
            if (INFINIT_INT == defSigValue) {
                return (signal);
            } else {
                return (defSigValue);
            }
        }

        break;
    }

    return (signal);
} // end function get_signal_value

/**
 * @brief       API: Is input signal a terminate signal?
 *
 * @param[in]   signal       #1: signal value
 *
 * @retval      TRUE         #1: yes
 * @retval      FALSE        #2: no
 */
bool_t
is_terminate_signal(int signal)
{
    switch (signal) {
    case QUICKPOOL_SIGKILL_USER:
    case QUICKPOOL_SIGKILL_OTHER:
    case QUICKPOOL_SIGKILL_RUNLIMIT:
    case QUICKPOOL_SIGKILL_DEADLINE:
    case QUICKPOOL_SIGKILL_PROCESSLIMIT:
    case QUICKPOOL_SIGKILL_FORCE:
    case QUICKPOOL_SIGKILL_REQUEUE:
    case QUICKPOOL_SIGKILL_CPULIMIT:
    case QUICKPOOL_SIGKILL_MEMLIMIT:
    case QUICKPOOL_SIGKILL_SWAPLIMIT:
        return TRUE;
    default:
        break;
    }

    return FALSE;
} // end function is_terminate_signal

/**
 * @brief       API: check what is defined in JOB_CONTROLS
 *
 * @param[in]   sigmap       #1: signal map of a queue
 * @param[in]   ctrlstring   #2: name to be checked
 *
 * @retval      TRUE         #1: defined
 * @retval      FALSE        #2: not defined
 */
bool_t
suspend_terminate_defined(int *sigmap, const char *ctrlstring)
{
    if ((0 == strcmp(ctrlstring, "WINDOW")) && (0 != sigmap[-QUICKPOOL_SIGSTOP_WINDOW])) {

        return TRUE;
    } else if ((0 == strcmp(ctrlstring, "USER")) && (0 != sigmap[-QUICKPOOL_SIGSTOP_USER])) {

        return TRUE;
    } else if ((0 == strcmp(ctrlstring, "LOAD")) && (0 != sigmap[-QUICKPOOL_SIGSTOP_LOAD])) {

        return TRUE;
    } else if ((0 == strcmp(ctrlstring, "PREEMPT")) && (0 != sigmap[-QUICKPOOL_SIGSTOP_PREEMPT])) {

        return TRUE;
    }

    return FALSE;
} // end function suspend_terminate_defined
